
#include "ipfe_default_ipfc_set.h"

// [*] C_IPFC_ResponseUser_Mean_and_Variance

C_IPFC_ResponseUser_Mean_and_Variance::C_IPFC_ResponseUser_Mean_and_Variance()
{
	SetMode(0);
	SetShapePatternList(NULL);
	this->ClearContent();
}

C_IPFC_ResponseUser_Mean_and_Variance::C_IPFC_ResponseUser_Mean_and_Variance(int Mode, const CShapePatternList* pFixedShapePatternList)
{
	SetMode(Mode);
	SetShapePatternList(pFixedShapePatternList);
	this->ClearContent();
}

C_IPFC_ResponseUser_Mean_and_Variance::~C_IPFC_ResponseUser_Mean_and_Variance()
{
}

void C_IPFC_ResponseUser_Mean_and_Variance::SetMode(int Mode)
{
	this->Mode = Mode;

	StatisticAmount = 0;
	if (Mode & MODE_MEAN_IN_CELL) ++StatisticAmount;
	if (Mode & MODE_MEAN_OVER_BLOCK) ++StatisticAmount;
	if (Mode & MODE_VARIANCE_IN_CELL) ++StatisticAmount;
	if (Mode & MODE_VARIANCE_OVER_BLOCK) ++StatisticAmount;
}

void C_IPFC_ResponseUser_Mean_and_Variance::SetShapePatternList(const CShapePatternList* pFixedShapePatternList)
{
	this->pFixedShapePatternList = pFixedShapePatternList;
	FeatureDimension = StatisticAmount * (pFixedShapePatternList==NULL ? 0 : pFixedShapePatternList->PatternAmount);
}

C_IPFC_ResponseUser* C_IPFC_ResponseUser_Mean_and_Variance::myClone() const
{
	return new C_IPFC_ResponseUser_Mean_and_Variance(this->Mode, this->pFixedShapePatternList);
}

size_t C_IPFC_ResponseUser_Mean_and_Variance::GetMemoryUsage() const
{
	return sizeof(const CShapePatternList*) + sizeof(int) * 3 + mapX1.GetMemoryUsage() + mapX2.GetMemoryUsage();
}

int C_IPFC_ResponseUser_Mean_and_Variance::GetInputResonseDimension() const
{
	return 1;
}

int C_IPFC_ResponseUser_Mean_and_Variance::GetFeatureDimension() const
{
	return FeatureDimension;
}

int C_IPFC_ResponseUser_Mean_and_Variance::RecomputeFeatureDimension()
{
	SetMode(Mode);
	SetShapePatternList(pFixedShapePatternList);
	return FeatureDimension;
}

void C_IPFC_ResponseUser_Mean_and_Variance::ClearContent()
{
	mapX1.ClearContent();
	mapX2.ClearContent();
}

void C_IPFC_ResponseUser_Mean_and_Variance::SetInputResponse(const double* pSrcResponse, int W, int H)
{
	int i;
	int WH = W * H;

	mapX1.myInit(pSrcResponse, W, H, 0, 0);

	if (Mode & (MODE_VARIANCE_IN_CELL | MODE_VARIANCE_OVER_BLOCK))
	{
		CSimpleTypeArray<double> temp_xx;
		temp_xx.Resize(WH);
		double* pd = temp_xx.pElement;
		const double* qd = pSrcResponse;
		for ( i = 0; i < WH; ++i ) *(pd++) = CMyMath::sqr(*(qd++));
		mapX2.myInit(temp_xx.pElement, W, H, 0, 0);
	}
}

void C_IPFC_ResponseUser_Mean_and_Variance::ComputeFeature(int x, int y, int FeatureIndex, double* DstData, bool* DstGotFlag)
{
	if (FeatureIndex<0 || FeatureIndex>=FeatureDimension) return;
	int ip = FeatureIndex / StatisticAmount;
	size_t BaseOffset = ((size_t)ip) * (size_t)StatisticAmount;
	DstData += BaseOffset;
	DstGotFlag += BaseOffset;

	int j, jn;
	int* pxl;
	int* pyl;
	int* pxh;
	int* pyh;
	double* pw;
	double s_area;
	double t1, t2, tt;

	jn = pFixedShapePatternList->GetPattern(pxl, pyl, pxh, pyh, pw, ip);
	CSimpleTypeArray<double> sx1_list; sx1_list.Resize(jn); double* p_sx1 = sx1_list.pElement;
	CSimpleTypeArray<double> sx2_list; sx2_list.Resize(jn); double* p_sx2 = sx2_list.pElement;
	CSimpleTypeArray<double> area_list; area_list.Resize(jn); double* p_area = area_list.pElement;
	CSimpleTypeArray<double> weight_list; weight_list.Resize(jn); double* p_weight = weight_list.pElement;

	for ( j = 0; j < jn; ++j )
	{
		p_sx1[j] = mapX1.CalcRectangle(x + *pxl, y + *pyl, x + *pxh, y + *pyh, false, true);
		if (Mode & (MODE_VARIANCE_IN_CELL | MODE_VARIANCE_OVER_BLOCK))
			p_sx2[j] = mapX2.CalcRectangle(x + *pxl, y + *pyl, x + *pxh, y + *pyh, false, true);
		p_area[j] = (*(pxh++) - *(pxl++)) * (*(pyh++) - *(pyl++));
		p_weight[j] = *(pw++);
	}

	if (Mode & MODE_MEAN_IN_CELL)
	{
		t1 = 0.0;
		for ( j = 0; j < jn; ++j )
			t1 += p_sx1[j] / p_area[j] * p_weight[j];
		*(DstData++) = t1;
		*(DstGotFlag++) = true;
	}

	if (Mode & MODE_MEAN_OVER_BLOCK)
	{
		t1 = 0.0; s_area = 0.0;
		for ( j = 0; j < jn; ++j )
		{
			t1 += p_sx1[j] * p_weight[j];
			s_area += p_area[j]; // * p_weight[j];
		}
		if (s_area<-EPS || s_area>+EPS) t1 /= s_area;
		*(DstData++) = t1;
		*(DstGotFlag++) = true;
	}

	if (Mode & MODE_VARIANCE_IN_CELL)
	{
		t2 = 0.0;
		for ( j = 0; j < jn; ++j )
		{
			tt = p_sx2[j] * p_area[j] - p_sx1[j] * p_sx1[j];
			t2 += sqrt(tt>0.0 ? tt : 0.0) / p_area[j] * p_weight[j];
		}
		*(DstData++) = t2;
		*(DstGotFlag++) = true;
	}

	if (Mode & MODE_VARIANCE_OVER_BLOCK)
	{
		t1 = 0.0; t2 = 0.0; s_area = 0.0;
		for ( j = 0; j < jn; ++j )
		{
			t1 += p_sx1[j] * p_weight[j];
			t2 += p_sx2[j] * p_weight[j] * p_weight[j];
			s_area += p_area[j]; // * p_weight[j];
		}
		if (s_area<-EPS || s_area>+EPS) t1 /= s_area;
		if (s_area<-EPS || s_area>+EPS) t2 /= s_area;
		tt = t2 - t1 * t1;
		t2 = sqrt(tt>0.0 ? tt : 0.0);
		*(DstData++) = t2;
		*(DstGotFlag++) = true;
	}
}

// [*] C_IPFC_ResponseUser_MeanAndVairance

C_IPFC_ResponseUser_MeanAndVairance::C_IPFC_ResponseUser_MeanAndVairance()
{
	SetShapePatternList(NULL);
}

C_IPFC_ResponseUser_MeanAndVairance::C_IPFC_ResponseUser_MeanAndVairance(const CShapePatternList* pFixedShapePatternList)
{
	SetShapePatternList(pFixedShapePatternList);
}

C_IPFC_ResponseUser_MeanAndVairance::~C_IPFC_ResponseUser_MeanAndVairance()
{
}

void C_IPFC_ResponseUser_MeanAndVairance::SetShapePatternList(const CShapePatternList* pFixedShapePatternList)
{
	this->pFixedShapePatternList = pFixedShapePatternList;
	FeatureDimension = 2 * (pFixedShapePatternList==NULL ? 0 : pFixedShapePatternList->PatternAmount);
}

C_IPFC_ResponseUser* C_IPFC_ResponseUser_MeanAndVairance::myClone() const
{
	return new C_IPFC_ResponseUser_MeanAndVairance(this->pFixedShapePatternList);
}

size_t C_IPFC_ResponseUser_MeanAndVairance::GetMemoryUsage() const
{
	return sizeof(const CShapePatternList*) + sizeof(int) + IntegralMeanAndVariance.GetMemoryUsage();
}

int C_IPFC_ResponseUser_MeanAndVairance::GetInputResonseDimension() const
{
	return 1;
}

int C_IPFC_ResponseUser_MeanAndVairance::GetFeatureDimension() const
{
	return FeatureDimension;
}

int C_IPFC_ResponseUser_MeanAndVairance::RecomputeFeatureDimension()
{
	SetShapePatternList(pFixedShapePatternList);
	return FeatureDimension;
}

void C_IPFC_ResponseUser_MeanAndVairance::ClearContent()
{
	IntegralMeanAndVariance.ClearContent();
}

void C_IPFC_ResponseUser_MeanAndVairance::SetInputResponse(const double* pSrcResponse, int W, int H)
{
	IntegralMeanAndVariance.myInit(pSrcResponse, W, H);
}

void C_IPFC_ResponseUser_MeanAndVairance::ComputeFeature(int x, int y, int FeatureIndex, double* DstData, bool* DstGotFlag)
{
	if (FeatureIndex<0 || FeatureIndex>=FeatureDimension) return;
	int ip = FeatureIndex / 2;
	FeatureIndex = ip * 2;

	int j, jn;
	int* pxl;
	int* pyl;
	int* pxh;
	int* pyh;
	double* pw;
	double t1, t2, tt1, tt2;

	jn = pFixedShapePatternList->GetPattern(pxl, pyl, pxh, pyh, pw, ip);
	t1 = t2 = 0.0;
	for ( j = 0; j < jn; ++j )
	{
		IntegralMeanAndVariance.CalcRectangle(tt1, tt2, x + *(pxl++), y + *(pyl++), x + *(pxh++), y + *(pyh++));
		t1 += tt1 * *pw;
		t2 += tt2 * *pw;
		++pw;
	}
	DstData[ip + ip + 0] = t1;
	DstData[ip + ip + 1] = t2;
	DstGotFlag[ip + ip + 0] = true;
	DstGotFlag[ip + ip + 1] = true;
}

// [*] C_IPFC_ResponseUser_BlockNormalizer

C_IPFC_ResponseUser_BlockNormalizer::C_IPFC_ResponseUser_BlockNormalizer()
{
	this->pNormalizer = NULL;
	this->fSharedNormalizer = false;

	SetInputResponseDimension(0);
	SetShapePatternList(NULL);
	SetIfAverageInCell(false);
	SetNormalizer(NULL, false);
}

C_IPFC_ResponseUser_BlockNormalizer::C_IPFC_ResponseUser_BlockNormalizer(
	int InputResponseDimension, const CShapePatternList* pFixedShapePatternList,
	bool fAverageInCell,
	CMyNormalizer* pNormalizer, bool fSharedNormalizer)
{
	this->pNormalizer = NULL;
	this->fSharedNormalizer = false;

	SetInputResponseDimension(InputResponseDimension);
	SetShapePatternList(pFixedShapePatternList);
	SetIfAverageInCell(fAverageInCell);
	SetNormalizer(pNormalizer, fSharedNormalizer);
}

C_IPFC_ResponseUser_BlockNormalizer::~C_IPFC_ResponseUser_BlockNormalizer()
{
	if (!this->fSharedNormalizer) CDataStructureTools::MyRelease_Single(this->pNormalizer);
}

void C_IPFC_ResponseUser_BlockNormalizer::SetInputResponseDimension(int InputResponseDimension)
{
	this->InputDimension = InputResponseDimension;
}

void C_IPFC_ResponseUser_BlockNormalizer::SetShapePatternList(const CShapePatternList* pFixedShapePatternList)
{
	this->pFixedShapePatternList = pFixedShapePatternList;

	BlockAmount = 0;
	this->FeatureDimension = 0;
	BlockFeatureStartList.Clear();

	if (pFixedShapePatternList == NULL) return;

	BlockAmount = pFixedShapePatternList->PatternAmount;
	BlockFeatureStartList = pFixedShapePatternList->pwlStart;
	int i;
	for ( i = 0; i <= BlockAmount; ++i )
		BlockFeatureStartList.pElement[i] *= this->InputDimension;

	this->FeatureDimension += pFixedShapePatternList->wAmount;
	this->FeatureDimension *= this->InputDimension;
}

void C_IPFC_ResponseUser_BlockNormalizer::SetIfAverageInCell(bool fAverageInCell)
{
	this->fAverageInCell = fAverageInCell;
}

void C_IPFC_ResponseUser_BlockNormalizer::SetNormalizer(CMyNormalizer* pNormalizer, bool fSharedNormalizer)
{
	if (!this->fSharedNormalizer) CDataStructureTools::MyRelease_Single(this->pNormalizer);
	this->pNormalizer = pNormalizer;
	this->fSharedNormalizer = fSharedNormalizer;
}

C_IPFC_ResponseUser* C_IPFC_ResponseUser_BlockNormalizer::myClone() const
{
	C_IPFC_ResponseUser_BlockNormalizer* ret = new C_IPFC_ResponseUser_BlockNormalizer(*this);
	ret->pNormalizer = pNormalizer->myClone();
	return ret;
}

size_t C_IPFC_ResponseUser_BlockNormalizer::GetMemoryUsage() const
{
	size_t ret = sizeof(*this) + IntegralResponseList.GetMemoryUsage() + BlockFeatureStartList.GetMemoryUsage();
	int i;
	for ( i = 0; i < InputDimension; ++i )
		ret += IntegralResponseList.pElement[i].GetMemoryUsage();
	return ret;
}

int C_IPFC_ResponseUser_BlockNormalizer::GetInputResonseDimension() const
{
	return InputDimension;
}

int C_IPFC_ResponseUser_BlockNormalizer::GetFeatureDimension() const
{
	return FeatureDimension;
}

int C_IPFC_ResponseUser_BlockNormalizer::RecomputeFeatureDimension()
{
	//SetInputResponse(this->InputDimension);
	SetShapePatternList(this->pFixedShapePatternList);
	return FeatureDimension;
}

void C_IPFC_ResponseUser_BlockNormalizer::ClearContent()
{
	IntegralResponseList.DeepClear();
}

void C_IPFC_ResponseUser_BlockNormalizer::SetInputResponse(const double* pSrcResponse, int W, int H)
{
	ClearContent();
	IntegralResponseList.Resize(InputDimension);
	int i;
	size_t WH = W * H;
	for ( i = 0; i < InputDimension; ++i )
	{
		IntegralResponseList.pElement[i].myInit(pSrcResponse, W, H);
		pSrcResponse += WH;
	}
}

void C_IPFC_ResponseUser_BlockNormalizer::ComputeFeature(int x, int y, int FeatureIndex, double* DstData, bool* DstGotFlag)
{
	int BlockIndex = (int)(upper_bound(BlockFeatureStartList.Begin(), BlockFeatureStartList.End(), FeatureIndex) - BlockFeatureStartList.Begin()) - 1;
	if (BlockIndex<0 || BlockIndex>=BlockAmount) return;

	int* pxl;
	int* pyl;
	int* pxh;
	int* pyh;
	double* pw;
	int CellAmount = pFixedShapePatternList->GetPattern(pxl, pyl, pxh, pyh, pw, BlockIndex);

	DstData += BlockFeatureStartList.pElement[BlockIndex];
	DstGotFlag += BlockFeatureStartList.pElement[BlockIndex];
	double* pd;
	bool* pgf;
	int i, j;

	pd = DstData; pgf = DstGotFlag;
	for ( j = 0; j < CellAmount; ++j )
	{
		for ( i = 0; i < InputDimension; ++i )
		{
			*(pd++) = pw[j] * IntegralResponseList.pElement[i].CalcRectangle(
				x + pxl[j], y + pyl[j],
				x + pxh[j], y + pyh[j],
				fAverageInCell, true);
			*(pgf++) = true;
		}
	}

	if (pNormalizer == NULL) return;

	pNormalizer->Normalize(DstData, (size_t)(pd - DstData));
}

// [*] C_IPFC_ResponseUser_2D_RectHistogram::CDescriptorConfig

C_IPFC_ResponseUser_2D_RectHistogram::CDescriptorConfig::CDescriptorConfig()
{
	SetDefaultParameters();
}

void C_IPFC_ResponseUser_2D_RectHistogram::CDescriptorConfig::SetDefaultParameters()
{
	myInit(9, 8.0, 8.0, 8, 16, 2, 2, 0.5, "l2-hys", 1.0, 0.2);
}

void C_IPFC_ResponseUser_2D_RectHistogram::CDescriptorConfig::myInit(istream& inStream)
{
	string strNormalizer;
	inStream>>BinAmount;
	inStream>>wCelPix>>hCelPix;
	inStream>>wWinCel>>hWinCel;
	inStream>>wBlkCel>>hBlkCel;
	inStream>>WeightScale;
	inStream>>strNormalizer;
	inStream>>e>>hysth;
	myInit(BinAmount, wCelPix, hCelPix, wWinCel, hWinCel, wBlkCel, hBlkCel, WeightScale, strNormalizer, e, hysth);
}

void C_IPFC_ResponseUser_2D_RectHistogram::CDescriptorConfig::myInit(
	int BinAmount,
	double wCelPix, double hCelPix,
	int wWinCel, int hWinCel,
	int wBlkCel, int hBlkCel,
	double WeightScale,
	string strNormalizer,
	double e, double hysTheshold
	)
{
	this->BinAmount = (BinAmount<1 ? 1 : BinAmount);
	this->wCelPix = wCelPix; this->hCelPix = hCelPix;
	this->wWinCel = wWinCel; this->hWinCel = hWinCel;
	this->wBlkCel = wBlkCel; this->hBlkCel = hBlkCel;
	this->WeightScale = WeightScale;

	this->aWinCel = this->wWinCel * this->hWinCel;
	this->aBlkCel = this->wBlkCel * this->hBlkCel;
	this->wWinBlk = this->wWinCel - this->wBlkCel + 1;
	this->hWinBlk = this->hWinCel - this->hBlkCel + 1;
	this->aWinBlk = this->wWinBlk * this->hWinBlk;
	this->lenBlkDescriptor = this->BinAmount * this->aBlkCel;
	this->lenWinDescriptor = this->lenBlkDescriptor * this->aWinBlk;

	this->base_blk_pix_x = 0.5 + this->wCelPix * 0.5 * (this->wBlkCel - this->wWinCel);
	this->base_blk_pix_y = 0.5 + this->hCelPix * 0.5 * (this->hBlkCel - this->hWinCel);

	this->normalizer = L2_NORM; this->hysth = 0.0;
	CDataStructureTools::ToLowerCase(strNormalizer);
	if (strNormalizer == "l2-hys")
	{
		this->normalizer = L2_HYS;
		this->hysth = hysTheshold;
	}

	this->e = e;
}

// [*] C_IPFC_ResponseUser_2D_RectHistogram::CResponseConfig

C_IPFC_ResponseUser_2D_RectHistogram::CResponseConfig::CResponseConfig()
{
	fAreBinsWrapped = true;
	fDoGlobalResponseNormalization = false;
	ResponseIndex_for_Weight = 0;
	ResponseIndex_for_Value = 1;
	ValueBoundA = -PI;
	ValueBoundB = +PI;
}

// [*] C_IPFC_ResponseUser_2D_RectHistogram

C_IPFC_ResponseUser_2D_RectHistogram::C_IPFC_ResponseUser_2D_RectHistogram()
{
}

C_IPFC_ResponseUser_2D_RectHistogram::C_IPFC_ResponseUser_2D_RectHistogram(
	const CDescriptorConfig& DescriptorConfig,
	const CResponseConfig& ResponseConfig
	)
{
	InitHistogramConfig(DescriptorConfig, ResponseConfig);
}

C_IPFC_ResponseUser_2D_RectHistogram::~C_IPFC_ResponseUser_2D_RectHistogram()
{
}

void C_IPFC_ResponseUser_2D_RectHistogram::InitHistogramConfig(
	const CDescriptorConfig& DescriptorConfig,
	const CResponseConfig& ResponseConfig
	)
{
	this->_DescriptorConfig = DescriptorConfig;
	this->_ResponseConfig = ResponseConfig;

	_Dim = _DescriptorConfig.lenWinDescriptor;
	_lenBlkDescriptor = _DescriptorConfig.lenBlkDescriptor;
	if (_lenBlkDescriptor < 1) _lenBlkDescriptor = 1;

	__fPreprocessed = false;
}

void C_IPFC_ResponseUser_2D_RectHistogram::Preprocess_and_ClearComputingHistogry()
{
	if (__fPreprocessed) return;
	__fPreprocessed = true;

	BlkCache.Resize(WH);
	BlkCache.Fill(-1);
	BlkData.Clear();

	Preprocess_A();
}

void C_IPFC_ResponseUser_2D_RectHistogram::SetResponseImage_A(const double* SrcResponse)
{
	matW_A.Resize(WH);
	matV_A.Resize(WH);
	matW_B.Resize(WH);
	matV_B.Resize(WH);

	int i,o1,o2;
	double tw,tv,tt;
	const double* qw = __QW_HEAD;
	const double* qv = __QV_HEAD;
	for ( i = 0; i < (int)WH; ++i )
	{
		tw = *qw; tv = *qv;
		qw += __QW_STEP; qv += __QV_STEP;

		tt = __HistogramConfig.SelectBin_Bounding(o1,o2,tv);
		matW_A.pElement[i] = tw * (1.0 - tt);
		matV_A.pElement[i] = o1;
		matW_B.pElement[i] = tw * tt;
		matV_B.pElement[i] = o2;
	}
}

void C_IPFC_ResponseUser_2D_RectHistogram::Preprocess_A()
{
	int i, tcb;
	double t;

	double lx_f = _DescriptorConfig.wCelPix * _DescriptorConfig.wBlkCel * 0.5;
	double ly_f = _DescriptorConfig.hCelPix * _DescriptorConfig.hBlkCel * 0.5;
	_dx = (int)(ceil(lx_f + _DescriptorConfig.wCelPix * 0.5) + EPS);
	_dy = (int)(ceil(ly_f + _DescriptorConfig.hCelPix * 0.5) + EPS);
	_gau_weight_x.Resize(_dx + _dx + 1); _q_gw_x = _gau_weight_x.pElement + _dx;
	_gau_weight_y.Resize(_dy + _dy + 1); _q_gw_y = _gau_weight_y.pElement + _dy;
	_cell_base_x.Resize(_dx + _dx + 1); _q_cb_x =_cell_base_x.pElement + _dx;
	_cell_base_y.Resize(_dy + _dy + 1); _q_cb_y =_cell_base_y.pElement + _dy;
	_lin_weight_x.Resize(_dx + _dx + 1); _q_lw_x =_lin_weight_x.pElement + _dx;
	_lin_weight_y.Resize(_dy + _dy + 1); _q_lw_y =_lin_weight_y.pElement + _dy;

	double kSx = _DescriptorConfig.WeightScale * lx_f;
	double kSy = _DescriptorConfig.WeightScale * ly_f;
	double sum_x = 0.0, sum_y = 0.0;
	for ( i = -_dx; i <= +_dx; ++i ) sum_x += (_q_gw_x[i] = CMyMath::gaussian(i + 0.0, 0.0, kSx));
	for ( i = -_dy; i <= +_dy; ++i ) sum_y += (_q_gw_y[i] = CMyMath::gaussian(0.0, i + 0.0, kSy));
	sum_x = _DescriptorConfig.wCelPix * _DescriptorConfig.wBlkCel / sum_x;
	sum_y = _DescriptorConfig.hCelPix * _DescriptorConfig.hBlkCel / sum_y;
	for ( i = -_dx; i <= +_dx; ++i ) _q_gw_x[i] *= sum_x;
	for ( i = -_dy; i <= +_dy; ++i ) _q_gw_y[i] *= sum_y;

	tcb = -1;
	t = _DescriptorConfig.wCelPix * (0.5 - _DescriptorConfig.wBlkCel / 2.0) - 0.5;
	for ( i = -_dx; i <= +_dx; ++i )
	{
		if (i > t)
		{
			t += _DescriptorConfig.wCelPix;
			++tcb;
		}
		_q_cb_x[i] = tcb;
		_q_lw_x[i] = (t - i) / _DescriptorConfig.wCelPix;
	}

	tcb = -1;
	t = _DescriptorConfig.hCelPix * (0.5 - _DescriptorConfig.hBlkCel / 2.0) - 0.5;
	for ( i = -_dy; i <= +_dy; ++i )
	{
		if (i > t)
		{
			t += _DescriptorConfig.hCelPix;
			++tcb;
		}
		_q_cb_y[i] = tcb;
		_q_lw_y[i] = (t - i) / _DescriptorConfig.hCelPix;
	}
}

void C_IPFC_ResponseUser_2D_RectHistogram::ComputeBlock_A(double* DstData, int center_x, int center_y)
{
	int i_dx, i_dy, ix, iy, cx, cy, j;
	double twa, twb;
	int tva, tvb;
	const double* qwA;
	const int* qvA;
	const double* qwB;
	const int* qvB;
	double wy1, wy2, wx1, wx2;
	double* pd1;
	double* pd2;
	double* pd;

	int BIN_AMOUNT = _DescriptorConfig.BinAmount;

	for ( j = 0; j < _lenBlkDescriptor; ++j ) DstData[j] = 0.0;
	for ( i_dy = -_dy; i_dy <= +_dy; ++i_dy )
	{
		iy = center_y + i_dy; iy = (iy<0 ? 0 : (iy<H ? iy : H-1));
		qwA = matW_A.pElement + iy * W;
		qvA = matV_A.pElement + iy * W;
		qwB = matW_B.pElement + iy * W;
		qvB = matV_B.pElement + iy * W;
		cy = _q_cb_y[i_dy]; wy2 = _q_gw_y[i_dy];
		wy1 = wy2 * _q_lw_y[i_dy]; wy2 -= wy1;

		if (cy+0>=0 && cy+0<_DescriptorConfig.hBlkCel)
			pd1 = DstData + BIN_AMOUNT * ((cy+0) * _DescriptorConfig.wBlkCel);
		else
			pd1 = NULL;
		if (cy+1>=0 && cy+1<_DescriptorConfig.hBlkCel)
			pd2 = DstData + BIN_AMOUNT * ((cy+1) * _DescriptorConfig.wBlkCel);
		else
			pd2 = NULL;

		for ( i_dx = -_dx; i_dx <= +_dx; ++i_dx )
		{
			ix = center_x + i_dx; ix = (ix<0 ? 0 : (ix<W ? ix : W-1));
			twa = qwA[ix]; tva = qvA[ix];
			twb = qwB[ix]; tvb = qvB[ix];
			cx = _q_cb_x[i_dx]; wx2 = _q_gw_x[i_dx];
			wx1 = wx2 * _q_lw_x[i_dx]; wx2 -= wx1;

			if (cx+0>=0 && cx+0<_DescriptorConfig.wBlkCel)
			{
				if (pd1 != NULL)
				{
					pd = pd1 + BIN_AMOUNT * (cx+0);
					pd[tva] += twa * wx1 * wy1;
					pd[tvb] += twb * wx1 * wy1;
				}
				if (pd2 != NULL)
				{
					pd = pd2 + BIN_AMOUNT * (cx+0);
					pd[tva] += twa * wx1 * wy2;
					pd[tvb] += twb * wx1 * wy2;
				}
			}

			if (cx+1>=0 && cx+1<_DescriptorConfig.wBlkCel)
			{
				if (pd1 != NULL)
				{
					pd = pd1 + BIN_AMOUNT * (cx+1);
					pd[tva] += twa * wx2 * wy1;
					pd[tvb] += twb * wx2 * wy1;
				}
				if (pd2 != NULL)
				{
					pd = pd2 + BIN_AMOUNT * (cx+1);
					pd[tva] += twa * wx2 * wy2;
					pd[tvb] += twb * wx2 * wy2;
				}
			}
		}
	}
}

C_IPFC_ResponseUser* C_IPFC_ResponseUser_2D_RectHistogram::myClone() const
{
	return new C_IPFC_ResponseUser_2D_RectHistogram(_DescriptorConfig, _ResponseConfig);
}

size_t C_IPFC_ResponseUser_2D_RectHistogram::GetMemoryUsage() const
{
	return sizeof(_DescriptorConfig) + sizeof(_ResponseConfig)
		+ sizeof(int) * 9 + sizeof(int*) * 2 + sizeof(double*) * 4 + sizeof(const double*) * 2
		+ sizeof(double) + sizeof(bool) + sizeof(__HistogramConfig)
		+ _gau_weight_x.GetMemoryUsage()
		+ _gau_weight_y.GetMemoryUsage()
		+ _cell_base_x.GetMemoryUsage()
		+ _cell_base_y.GetMemoryUsage()
		+ _lin_weight_x.GetMemoryUsage()
		+ _lin_weight_y.GetMemoryUsage()
		+ matW_A.GetMemoryUsage()
		+ matW_B.GetMemoryUsage()
		+ matV_A.GetMemoryUsage()
		+ matV_B.GetMemoryUsage()
		+ BlkCache.GetMemoryUsage()
		+ BlkData.GetMemoryUsage()
		;
}

int C_IPFC_ResponseUser_2D_RectHistogram::GetInputResonseDimension() const
{
	return 2;
}

int C_IPFC_ResponseUser_2D_RectHistogram::GetFeatureDimension() const
{
	return _DescriptorConfig.lenWinDescriptor;
}

int C_IPFC_ResponseUser_2D_RectHistogram::RecomputeFeatureDimension()
{
	return _DescriptorConfig.lenWinDescriptor;
}

void C_IPFC_ResponseUser_2D_RectHistogram::ClearContent()
{
	W = H = WH = 0;
	//TODO
}

void C_IPFC_ResponseUser_2D_RectHistogram::SetInputResponse(const double* pSrcResponse, int W, int H)
{
	this->W = W;
	this->H = H;
	this->WH = W * H;

	__ONE = 1.0;
	__QW_HEAD = __QV_HEAD = &__ONE;
	__QV_STEP = __QV_STEP = 0;
	if (_ResponseConfig.ResponseIndex_for_Weight>=0 && _ResponseConfig.ResponseIndex_for_Weight<2)
	{
		__QW_HEAD = pSrcResponse + WH * _ResponseConfig.ResponseIndex_for_Weight;
		__QW_STEP = 1;
	}
	if (_ResponseConfig.ResponseIndex_for_Value>=0 && _ResponseConfig.ResponseIndex_for_Value<2)
	{
		__QV_HEAD = pSrcResponse + WH * _ResponseConfig.ResponseIndex_for_Value;
		__QV_STEP = 1;
	}

	int tba = _DescriptorConfig.BinAmount;
	bool tfbw = _ResponseConfig.fAreBinsWrapped;
	double vba = _ResponseConfig.ValueBoundA;
	double vbb = _ResponseConfig.ValueBoundB;
	if (_ResponseConfig.fDoGlobalResponseNormalization)
	{
		int i;
		double t,s,ss;
		const double* qv;

		s = ss = 0.0;
		qv = __QV_HEAD;
		for ( i = 0; i < (int)WH; ++i )
		{
			t = *qv; qv += __QV_STEP;
			s += t; ss += t * t;
		}
		s /= WH; ss = ss/WH - s*s;
		if (ss<EPS*EPS) ss = 0.5; else ss = sqrt(ss);

		vba = s + ss * (-2.0);
		vbb = s + ss * (+2.0);
	}
	__HistogramConfig.myInit(tba, tfbw, vba, vbb);

	SetResponseImage_A(pSrcResponse);

	__fPreprocessed = false;
}

void C_IPFC_ResponseUser_2D_RectHistogram::ComputeFeature(int x, int y, int FeatureIndex, double* DstData, bool* DstGotFlag)
{
	int i, j, ix, iy, t_pos;
	double tx, ty;
	double* pchd;

	if (FeatureIndex<0 || FeatureIndex>=_Dim) return;

	Preprocess_and_ClearComputingHistogry();

	int blkIndex = FeatureIndex / _lenBlkDescriptor;
	DstData += blkIndex * _lenBlkDescriptor;
	DstGotFlag += blkIndex * _lenBlkDescriptor;
	int xBlk = blkIndex % _DescriptorConfig.wWinBlk;
	int yBlk = blkIndex / _DescriptorConfig.wWinBlk;

	tx = x + _DescriptorConfig.base_blk_pix_x + _DescriptorConfig.wCelPix * xBlk;
	ty = y + _DescriptorConfig.base_blk_pix_y + _DescriptorConfig.hCelPix * yBlk;

	if (tx<0 || tx>=W || ty<0 || ty>=H)
	{
		tx = (tx<0 ? 0 : (tx<W ? tx : W-1));
		ty = (ty<0 ? 0 : (ty<H ? ty : H-1));
	}

	ix = (int)tx; iy = (int) ty; i = ix + iy * W;

	t_pos = BlkCache.pElement[i];
	if (t_pos < 0)
	{
		t_pos = (int)BlkData.Size;
		BlkCache.pElement[i] = t_pos;
		BlkData.Resize(t_pos + _lenBlkDescriptor, 0.0);

		pchd = BlkData.pElement + t_pos;
		ComputeBlock_A(pchd, ix, iy);

		// Do Normalization
		if (_DescriptorConfig.normalizer==CDescriptorConfig::L2_NORM || _DescriptorConfig.normalizer==CDescriptorConfig::L2_HYS)
			CMyMath::L2_Normalize(pchd, _lenBlkDescriptor, _DescriptorConfig.e / _lenBlkDescriptor);
		if (_DescriptorConfig.normalizer==CDescriptorConfig::L2_HYS)
		{
			double th = _DescriptorConfig.hysth;
			for ( j = 0; j < _lenBlkDescriptor; ++j )
				if (pchd[j] > th)
					pchd[j] = th;
			j = j;
			CMyMath::L2_Normalize(pchd, _lenBlkDescriptor, 0.01 / _lenBlkDescriptor);
		}
	}

	pchd = BlkData.pElement + t_pos;
	for ( i = 0; i < _lenBlkDescriptor; ++i ) DstData[i] = pchd[i];
	for ( i = 0; i < _lenBlkDescriptor; ++i ) DstGotFlag[i] = true;
}

////// [*] CRectHistogram_of_2D_Response_IPFC::CDescriptorConfig
////
////CRectHistogram_of_2D_Response_IPFC::CDescriptorConfig::CDescriptorConfig()
////{
////	Clear();
////}
////
////void CRectHistogram_of_2D_Response_IPFC::CDescriptorConfig::Clear()
////{
////	myInit(9, 8.0, 8.0, 8, 16, 2, 2, 0.5, "l2-hys", 1.0, 0.2);
////}
////
////void CRectHistogram_of_2D_Response_IPFC::CDescriptorConfig::myInit(istream& inStream)
////{
////	string strNormalizer;
////	inStream>>BinAmount;
////	inStream>>wCelPix>>hCelPix;
////	inStream>>wWinCel>>hWinCel;
////	inStream>>wBlkCel>>hBlkCel;
////	inStream>>WeightScale;
////	inStream>>strNormalizer;
////	inStream>>e>>hysth;
////	myInit(BinAmount, wCelPix, hCelPix, wWinCel, hWinCel, wBlkCel, hBlkCel, WeightScale, strNormalizer, e, hysth);
////}
////
////void CRectHistogram_of_2D_Response_IPFC::CDescriptorConfig::myInit(
////	int BinAmount,
////	double wCelPix, double hCelPix,
////	int wWinCel, int hWinCel,
////	int wBlkCel, int hBlkCel,
////	double WeightScale,
////	string strNormalizer,
////	double e, double hysTheshold
////	)
////{
////	this->BinAmount = (BinAmount<1 ? 1 : BinAmount);
////	this->wCelPix = wCelPix; this->hCelPix = hCelPix;
////	this->wWinCel = wWinCel; this->hWinCel = hWinCel;
////	this->wBlkCel = wBlkCel; this->hBlkCel = hBlkCel;
////	this->WeightScale = WeightScale;
////
////	this->aWinCel = this->wWinCel * this->hWinCel;
////	this->aBlkCel = this->wBlkCel * this->hBlkCel;
////	this->wWinBlk = this->wWinCel - this->wBlkCel + 1;
////	this->hWinBlk = this->hWinCel - this->hBlkCel + 1;
////	this->aWinBlk = this->wWinBlk * this->hWinBlk;
////	this->lenBlkDescriptor = this->BinAmount * this->aBlkCel;
////	this->lenWinDescriptor = this->lenBlkDescriptor * this->aWinBlk;
////
////	this->base_blk_pix_x = 0.5 + this->wCelPix * 0.5 * (this->wBlkCel - this->wWinCel);
////	this->base_blk_pix_y = 0.5 + this->hCelPix * 0.5 * (this->hBlkCel - this->hWinCel);
////
////	this->normalizer = L2_NORM; this->hysth = 0.0;
////	CDataStructureTools::ToLowerCase(strNormalizer);
////	if (strNormalizer == "l2-hys")
////	{
////		this->normalizer = L2_HYS;
////		this->hysth = hysTheshold;
////	}
////
////	this->e = e;
////}
////
////// [*] CRectHistogram_of_2D_Response_IPFC
////
////CRectHistogram_of_2D_Response_IPFC::CRectHistogram_of_2D_Response_IPFC()
////{
////	InitHistogramConfig(NULL, NULL);
////}
////
////CRectHistogram_of_2D_Response_IPFC::CRectHistogram_of_2D_Response_IPFC(
////	CImageFilterBank* pFixedImageFilterBank,
////	int ImageExtent,
////	const CSimpleTypeArray<int> InputResponseList,
////	const CResponseConfig* pFixedResponseConfig,
////	const CDescriptorConfig* pFixDescriptorConfig
////	)
////	: CFilterResponseIPFC(pFixedImageFilterBank, ImageExtent, InputResponseList)
////{
////	InitHistogramConfig(
////		pFixedResponseConfig,
////		pFixDescriptorConfig
////		);
////}
////
////CRectHistogram_of_2D_Response_IPFC::~CRectHistogram_of_2D_Response_IPFC()
////{
////	//TODO
////}
////
////void CRectHistogram_of_2D_Response_IPFC::InitHistogramConfig(
////	const CResponseConfig* pFixedResponseConfig,
////	const CDescriptorConfig* pFixDescriptorConfig
////	)
////{
////	_pResponseConfig = pFixedResponseConfig;
////	_pDescriptorConfig = pFixDescriptorConfig;
////
////	_Dim = (_pDescriptorConfig==NULL ? 0 : _pDescriptorConfig->lenWinDescriptor);
////	_lenBlkDescriptor = (_pDescriptorConfig==NULL ? 0 : _pDescriptorConfig->lenBlkDescriptor);
////	if (_lenBlkDescriptor < 1) _lenBlkDescriptor = 1;
////
////	__fPreprocessed = false;
////}
////
////CImagePositionFeatureCalculator* CRectHistogram_of_2D_Response_IPFC::myClone() const
////{
////	return new CRectHistogram_of_2D_Response_IPFC(pImageFilterBank, ImageExtent, InputResponseList, _pResponseConfig, _pDescriptorConfig);
////}
////
////void CRectHistogram_of_2D_Response_IPFC::Preprocess_and_ClearComputingHistogry()
////{
////	if (__fPreprocessed) return;
////	__fPreprocessed = true;
////
////	BlkCache.Resize(WH);
////	BlkCache.Fill(-1);
////	BlkData.Clear();
////
////	Preprocess_A();
////}
////
////void CRectHistogram_of_2D_Response_IPFC::SetResponseImage(const double* SrcResponse)
////{
////	__ONE = 1.0;
////	__QW_HEAD = __QV_HEAD = &__ONE;
////	__QV_STEP = __QV_STEP = 0;
////	if (_pResponseConfig!=NULL && _pResponseConfig->ResponseIndex_for_Weight>=0 && _pResponseConfig->ResponseIndex_for_Weight<V)
////	{
////		__QW_HEAD = SrcResponse + WH * _pResponseConfig->ResponseIndex_for_Weight;
////		__QW_STEP = 1;
////	}
////	if (_pResponseConfig!=NULL && _pResponseConfig->ResponseIndex_for_Value>=0 && _pResponseConfig->ResponseIndex_for_Value<V)
////	{
////		__QV_HEAD = SrcResponse + WH * _pResponseConfig->ResponseIndex_for_Value;
////		__QV_STEP = 1;
////	}
////
////	int tba = (_pDescriptorConfig==NULL ? 1 : _pDescriptorConfig->BinAmount);
////	bool tfbw = (_pResponseConfig==NULL ? false : _pResponseConfig->fAreBinsWrapped);
////	double vba = (_pResponseConfig==NULL ? 0.0 : _pResponseConfig->ValueBoundA);
////	double vbb = (_pResponseConfig==NULL ? 1.0 : _pResponseConfig->ValueBoundB);
////	if (_pResponseConfig!=NULL && _pResponseConfig->fDoGlobalResponseNormalization)
////	{
////		int i;
////		double t,s,ss;
////		const double* qv;
////
////		s = ss = 0.0;
////		qv = __QV_HEAD;
////		for ( i = 0; i < (int)WH; ++i )
////		{
////			t = *qv; qv += __QV_STEP;
////			s += t; ss += t * t;
////		}
////		s /= WH; ss = ss/WH - s*s;
////		if (ss<EPS*EPS) ss = 0.5; else ss = sqrt(ss);
////
////		vba = s + ss * (-2.0);
////		vbb = s + ss * (+2.0);
////	}
////	__HistogramConfig.myInit(tba, tfbw, vba, vbb);
////
////	SetResponseImage_A(SrcResponse);
////
////	__fPreprocessed = false;
////}
////
////int CRectHistogram_of_2D_Response_IPFC::GetFeatureDimension()
////{
////	return _Dim;
////}
////
////void CRectHistogram_of_2D_Response_IPFC::CalcFeature(
////	int x, int y, int FeatureIndex,
////	double* DstData, bool* DstGotFlag
////	)
////{
////	int i, j, ix, iy, t_pos;
////	double tx, ty;
////	double* pchd;
////
////	if (FeatureIndex<0 || FeatureIndex>=_Dim) return;
////
////	Preprocess_and_ClearComputingHistogry();
////
////	int blkIndex = FeatureIndex / _lenBlkDescriptor;
////	DstData += blkIndex * _lenBlkDescriptor;
////	DstGotFlag += blkIndex * _lenBlkDescriptor;
////	int xBlk = blkIndex % _pDescriptorConfig->wWinBlk;
////	int yBlk = blkIndex / _pDescriptorConfig->wWinBlk;
////
////	tx = x + _pDescriptorConfig->base_blk_pix_x + _pDescriptorConfig->wCelPix * xBlk;
////	ty = y + _pDescriptorConfig->base_blk_pix_y + _pDescriptorConfig->hCelPix * yBlk;
////
////	if (tx<0 || tx>=W || ty<0 || ty>=H)
////	{
////		//cout<<"ERROR?! : "<<tx<<" "<<ty<<endl;
////		tx = (tx<0 ? 0 : (tx<W ? tx : W-1));
////		ty = (ty<0 ? 0 : (ty<H ? ty : H-1));
////	}
////
////	ix = (int)tx; iy = (int) ty; i = ix + iy * W;
////
////	t_pos = BlkCache.pElement[i];
////	if (t_pos < 0)
////	{
////		t_pos = (int)BlkData.Size;
////		BlkCache.pElement[i] = t_pos;
////		BlkData.Resize(t_pos + _lenBlkDescriptor, 0.0);
////
////		pchd = BlkData.pElement + t_pos;
////		ComputeBlock_A(pchd, ix, iy);
////
////		// Do Normalization
////		if (_pDescriptorConfig->normalizer==CDescriptorConfig::L2_NORM || _pDescriptorConfig->normalizer==CDescriptorConfig::L2_HYS)
////			CMyMath::L2_Normalize(pchd, _lenBlkDescriptor, _pDescriptorConfig->e / _lenBlkDescriptor);
////		if (_pDescriptorConfig->normalizer==CDescriptorConfig::L2_HYS)
////		{
////			double th = _pDescriptorConfig->hysth;
////			for ( j = 0; j < _lenBlkDescriptor; ++j )
////				if (pchd[j] > th)
////					pchd[j] = th;
////			j = j;
////			CMyMath::L2_Normalize(pchd, _lenBlkDescriptor, 0.01 / _lenBlkDescriptor);
////		}
////	}
////
////	pchd = BlkData.pElement + t_pos;
////	for ( i = 0; i < _lenBlkDescriptor; ++i ) DstData[i] = pchd[i];
////	for ( i = 0; i < _lenBlkDescriptor; ++i ) DstGotFlag[i] = true;
////}
////
////void CRectHistogram_of_2D_Response_IPFC::SetResponseImage_A(const double* SrcResponse)
////{
////	matW_A.Resize(WH);
////	matV_A.Resize(WH);
////	matW_B.Resize(WH);
////	matV_B.Resize(WH);
////
////	int i,o1,o2;
////	double tw,tv,tt;
////	const double* qw = __QW_HEAD;
////	const double* qv = __QV_HEAD;
////	for ( i = 0; i < (int)WH; ++i )
////	{
////		tw = *qw; tv = *qv;
////		qw += __QW_STEP; qv += __QV_STEP;
////
////		tt = __HistogramConfig.SelectBin_Bounding(o1,o2,tv);
////		matW_A.pElement[i] = tw * (1.0 - tt);
////		matV_A.pElement[i] = o1;
////		matW_B.pElement[i] = tw * tt;
////		matV_B.pElement[i] = o2;
////	}
////}
////
////void CRectHistogram_of_2D_Response_IPFC::Preprocess_A()
////{
////	int i, tcb;
////	double t;
////
////	double lx_f = _pDescriptorConfig->wCelPix * _pDescriptorConfig->wBlkCel * 0.5;
////	double ly_f = _pDescriptorConfig->hCelPix * _pDescriptorConfig->hBlkCel * 0.5;
////	_dx = (int)(ceil(lx_f + _pDescriptorConfig->wCelPix * 0.5) + EPS);
////	_dy = (int)(ceil(ly_f + _pDescriptorConfig->hCelPix * 0.5) + EPS);
////	_gau_weight_x.Resize(_dx + _dx + 1); _q_gw_x = _gau_weight_x.pElement + _dx;
////	_gau_weight_y.Resize(_dy + _dy + 1); _q_gw_y = _gau_weight_y.pElement + _dy;
////	_cell_base_x.Resize(_dx + _dx + 1); _q_cb_x =_cell_base_x.pElement + _dx;
////	_cell_base_y.Resize(_dy + _dy + 1); _q_cb_y =_cell_base_y.pElement + _dy;
////	_lin_weight_x.Resize(_dx + _dx + 1); _q_lw_x =_lin_weight_x.pElement + _dx;
////	_lin_weight_y.Resize(_dy + _dy + 1); _q_lw_y =_lin_weight_y.pElement + _dy;
////
////	double kSx = _pDescriptorConfig->WeightScale * lx_f;
////	double kSy = _pDescriptorConfig->WeightScale * ly_f;
////	double sum_x = 0.0, sum_y = 0.0;
////	for ( i = -_dx; i <= +_dx; ++i ) sum_x += (_q_gw_x[i] = CMyMath::gaussian(i + 0.0, 0.0, kSx));
////	for ( i = -_dy; i <= +_dy; ++i ) sum_y += (_q_gw_y[i] = CMyMath::gaussian(0.0, i + 0.0, kSy));
////	sum_x = _pDescriptorConfig->wCelPix * _pDescriptorConfig->wBlkCel / sum_x;
////	sum_y = _pDescriptorConfig->hCelPix * _pDescriptorConfig->hBlkCel / sum_y;
////	for ( i = -_dx; i <= +_dx; ++i ) _q_gw_x[i] *= sum_x;
////	for ( i = -_dy; i <= +_dy; ++i ) _q_gw_y[i] *= sum_y;
////
////	tcb = -1;
////	t = _pDescriptorConfig->wCelPix * (0.5 - _pDescriptorConfig->wBlkCel / 2.0) - 0.5;
////	for ( i = -_dx; i <= +_dx; ++i )
////	{
////		if (i > t)
////		{
////			t += _pDescriptorConfig->wCelPix;
////			++tcb;
////		}
////		_q_cb_x[i] = tcb;
////		_q_lw_x[i] = (t - i) / _pDescriptorConfig->wCelPix;
////	}
////
////	tcb = -1;
////	t = _pDescriptorConfig->hCelPix * (0.5 - _pDescriptorConfig->hBlkCel / 2.0) - 0.5;
////	for ( i = -_dy; i <= +_dy; ++i )
////	{
////		if (i > t)
////		{
////			t += _pDescriptorConfig->hCelPix;
////			++tcb;
////		}
////		_q_cb_y[i] = tcb;
////		_q_lw_y[i] = (t - i) / _pDescriptorConfig->hCelPix;
////	}
////}
////
////void CRectHistogram_of_2D_Response_IPFC::ComputeBlock_A(double* DstData, int center_x, int center_y)
////{
////	int i_dx, i_dy, ix, iy, cx, cy, j;
////	double twa, twb;
////	int tva, tvb;
////	const double* qwA;
////	const int* qvA;
////	const double* qwB;
////	const int* qvB;
////	double wy1, wy2, wx1, wx2;
////	double* pd1;
////	double* pd2;
////	double* pd;
////
////	int BIN_AMOUNT = _pDescriptorConfig->BinAmount;
////
////	for ( j = 0; j < _lenBlkDescriptor; ++j ) DstData[j] = 0.0;
////	for ( i_dy = -_dy; i_dy <= +_dy; ++i_dy )
////	{
////		iy = center_y + i_dy; iy = (iy<0 ? 0 : (iy<H ? iy : H-1));
////		qwA = matW_A.pElement + iy * W;
////		qvA = matV_A.pElement + iy * W;
////		qwB = matW_B.pElement + iy * W;
////		qvB = matV_B.pElement + iy * W;
////		cy = _q_cb_y[i_dy]; wy2 = _q_gw_y[i_dy];
////		wy1 = wy2 * _q_lw_y[i_dy]; wy2 -= wy1;
////
////		if (cy+0>=0 && cy+0<_pDescriptorConfig->hBlkCel)
////			pd1 = DstData + BIN_AMOUNT * ((cy+0) * _pDescriptorConfig->wBlkCel);
////		else
////			pd1 = NULL;
////		if (cy+1>=0 && cy+1<_pDescriptorConfig->hBlkCel)
////			pd2 = DstData + BIN_AMOUNT * ((cy+1) * _pDescriptorConfig->wBlkCel);
////		else
////			pd2 = NULL;
////
////		for ( i_dx = -_dx; i_dx <= +_dx; ++i_dx )
////		{
////			ix = center_x + i_dx; ix = (ix<0 ? 0 : (ix<W ? ix : W-1));
////			twa = qwA[ix]; tva = qvA[ix];
////			twb = qwB[ix]; tvb = qvB[ix];
////			cx = _q_cb_x[i_dx]; wx2 = _q_gw_x[i_dx];
////			wx1 = wx2 * _q_lw_x[i_dx]; wx2 -= wx1;
////
////			if (cx+0>=0 && cx+0<_pDescriptorConfig->wBlkCel)
////			{
////				if (pd1 != NULL)
////				{
////					pd = pd1 + BIN_AMOUNT * (cx+0);
////					pd[tva] += twa * wx1 * wy1;
////					pd[tvb] += twb * wx1 * wy1;
////				}
////				if (pd2 != NULL)
////				{
////					pd = pd2 + BIN_AMOUNT * (cx+0);
////					pd[tva] += twa * wx1 * wy2;
////					pd[tvb] += twb * wx1 * wy2;
////				}
////			}
////
////			if (cx+1>=0 && cx+1<_pDescriptorConfig->wBlkCel)
////			{
////				if (pd1 != NULL)
////				{
////					pd = pd1 + BIN_AMOUNT * (cx+1);
////					pd[tva] += twa * wx2 * wy1;
////					pd[tvb] += twb * wx2 * wy1;
////				}
////				if (pd2 != NULL)
////				{
////					pd = pd2 + BIN_AMOUNT * (cx+1);
////					pd[tva] += twa * wx2 * wy2;
////					pd[tvb] += twb * wx2 * wy2;
////				}
////			}
////		}
////	}
////}

////////// [*] CResponseMeanIPFC
////////
////////CResponseMeanIPFC::CResponseMeanIPFC()
////////{
////////	IntegralResponseList.Clear();
////////}
////////
////////CResponseMeanIPFC::CResponseMeanIPFC(
////////	CImageFilterBank* pFixedImageFilterBank,
////////	int ImageExtent,
////////	const CSimpleTypeArray<int>& InputResponseList,
////////	const CShapePatternList* pFixedShapePatternList
////////	)
////////	: CFilterResponseIPFC(pFixedImageFilterBank, ImageExtent, InputResponseList)
////////{
////////	InitPatternList(pFixedShapePatternList);
////////	IntegralResponseList.Clear();
////////}
////////
////////CResponseMeanIPFC::~CResponseMeanIPFC()
////////{
////////	//TODO
////////}
////////
////////void CResponseMeanIPFC::InitPatternList(const CShapePatternList* pFixedShapePatternList)
////////{
////////	_pShapePatternList = pFixedShapePatternList;
////////	_PatternAmount = _pShapePatternList->PatternAmount;
////////}
////////
////////CImagePositionFeatureCalculator* CResponseMeanIPFC::myClone() const
////////{
////////	return new CResponseMeanIPFC(pImageFilterBank, ImageExtent, InputResponseList, _pShapePatternList);
////////}
////////
////////void CResponseMeanIPFC::SetResponseImage(const double* SrcResponse)
////////{
////////	int i;
////////
////////	IntegralResponseList.Resize(V);
////////	for ( i = 0; i < V; ++i )
////////		IntegralResponseList.pElement[i].myInit(SrcResponse + WH * i, W, H);
////////}
////////
////////int CResponseMeanIPFC::GetFeatureDimension()
////////{
////////	return V * _PatternAmount;
////////}
////////
////////void CResponseMeanIPFC::CalcFeature(
////////	int x, int y, int FeatureIndex,
////////	double* DstData, bool* DstGotFlag
////////	)
////////{
////////	int i,j,jn,m;
////////	CIntegralResponse* pIntRes;
////////	double* pfd;
////////	bool* pfg;
////////	int* pxl;
////////	int* pyl;
////////	int* pxh;
////////	int* pyh;
////////	double* pw;
////////	double t,tt;
////////
////////	m = _PatternAmount;
////////
////////	if (FeatureIndex < 0) return;
////////	int v_index = FeatureIndex / m;
////////	if (v_index >= V) return;
////////
////////	pIntRes = IntegralResponseList.pElement + v_index;
////////	FeatureIndex %= m;
////////	pfd = DstData + m * v_index;
////////	pfg = DstGotFlag + m * v_index;
////////
////////	for ( i = 0; i < _PatternAmount; ++i )
////////	{
////////		jn = _pShapePatternList->GetPattern(pxl, pyl, pxh, pyh, pw, i);
////////		t = 0.0;
////////		for ( j = 0; j < jn; ++j )
////////		{
////////			tt = pIntRes->CalcRectangle(x + *(pxl++), y + *(pyl++), x + *(pxh++), y + *(pyh++), true, true);
////////			t += *(pw++) * tt;
////////		}
////////		*(pfd++) = t;
////////		*(pfg++) = true;
////////	}
////////}
////////
////////size_t CResponseMeanIPFC::GetMemoryUsage() const
////////{
////////	size_t ret = CFilterResponseIPFC::GetMemoryUsage() + sizeof(const CShapePatternList*) + sizeof(int) + IntegralResponseList.GetMemoryUsage();
////////	int i;
////////	for ( i = 0; i < (int)IntegralResponseList.Size; ++i )
////////		ret += IntegralResponseList.pElement[i].GetMemoryUsage();
////////	return ret;
////////}
////////
////////// [*] CResponseMeanAndVarianceIPFC
////////
////////CResponseMeanAndVarianceIPFC::CResponseMeanAndVarianceIPFC()
////////{
////////	IntegralMeanAndVarianceList.Clear();
////////}
////////
////////CResponseMeanAndVarianceIPFC::CResponseMeanAndVarianceIPFC(
////////	CImageFilterBank* pFixedImageFilterBank,
////////	int ImageExtent,
////////	const CSimpleTypeArray<int>& InputResponseList,
////////	const CShapePatternList* pFixedShapePatternList
////////	)
////////	: CFilterResponseIPFC(pFixedImageFilterBank, ImageExtent, InputResponseList)
////////{
////////	InitPatternList(pFixedShapePatternList);
////////	IntegralMeanAndVarianceList.Clear();
////////}
////////
////////CResponseMeanAndVarianceIPFC::~CResponseMeanAndVarianceIPFC()
////////{
////////	//TODO
////////}
////////
////////void CResponseMeanAndVarianceIPFC::InitPatternList(const CShapePatternList* pFixedShapePatternList)
////////{
////////	_pShapePatternList = pFixedShapePatternList;
////////	_PatternAmount = _pShapePatternList->PatternAmount;
////////}
////////
////////CImagePositionFeatureCalculator* CResponseMeanAndVarianceIPFC::myClone() const
////////{
////////	return new CResponseMeanAndVarianceIPFC(pImageFilterBank, ImageExtent, InputResponseList, _pShapePatternList);
////////}
////////
////////void CResponseMeanAndVarianceIPFC::SetResponseImage(const double* SrcResponse)
////////{
////////	int i;
////////
////////	IntegralMeanAndVarianceList.Resize(V);
////////	for ( i = 0; i < V; ++i )
////////		IntegralMeanAndVarianceList.pElement[i].myInit(SrcResponse + WH * i, W, H);
////////}
////////
////////int CResponseMeanAndVarianceIPFC::GetFeatureDimension()
////////{
////////	return V * _PatternAmount * 2;
////////}
////////
////////void CResponseMeanAndVarianceIPFC::CalcFeature(
////////	int x, int y, int FeatureIndex,
////////	double* DstData, bool* DstGotFlag
////////	)
////////{
////////	int i,j,jn,m;
////////	CIntegralMeanAndVariance* pIntMV;
////////	double* pfd;
////////	bool* pfg;
////////	int* pxl;
////////	int* pyl;
////////	int* pxh;
////////	int* pyh;
////////	double* pw;
////////	double t1,t2,tt1,tt2;
////////
////////	m = _PatternAmount * 2;
////////
////////	if (FeatureIndex < 0) return;
////////	int v_index = FeatureIndex / m;
////////	if (v_index >= V) return;
////////
////////	pIntMV = IntegralMeanAndVarianceList.pElement + v_index;
////////	FeatureIndex %= m;
////////	pfd = DstData + m * v_index;
////////	pfg = DstGotFlag + m * v_index;
////////
////////	for ( i = 0; i < _PatternAmount; ++i )
////////	{
////////		jn = _pShapePatternList->GetPattern(pxl, pyl, pxh, pyh, pw, i);
////////		t1 = t2 = 0.0;
////////		for ( j = 0; j < jn; ++j )
////////		{
////////			pIntMV->CalcRectangle(tt1, tt2, x + *(pxl++), y + *(pyl++), x + *(pxh++), y + *(pyh++));
////////			t1 += tt1 * *pw;
////////			t2 += tt2 * *pw;
////////			++pw;
////////		}
////////		*(pfd++) = t1;
////////		*(pfg++) = true;
////////		*(pfd++) = t2;
////////		*(pfg++) = true;
////////	}
////////}
////////
////////size_t CResponseMeanAndVarianceIPFC::GetMemoryUsage() const
////////{
////////	size_t ret = CFilterResponseIPFC::GetMemoryUsage() + sizeof(const CShapePatternList*) + sizeof(int) + IntegralMeanAndVarianceList.GetMemoryUsage();
////////	int i;
////////	for ( i = 0; i < (int)IntegralMeanAndVarianceList.Size; ++i )
////////		ret += IntegralMeanAndVarianceList.pElement[i].GetMemoryUsage();
////////	return ret;
////////}

